﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright company="DHGMS Solutions" file="Database.cs">
//   2004-2012 DHGMS Solutions. Some Rights Reserved. Licensed under GNU General Public License version 2 (GPLv2)
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Dhgms.TplHelper.Controller.Task.SqlBulkCopy
{
    using System.Data.Common;
    using System.Data.SqlClient;

    using Dhgms.TplHelper.Model.Info;

    /// <summary>
    /// Base class for SQL Bulk Copy Tasks that use a database as the source
    /// </summary>
    public abstract class Database<TParameterClass> : DataReader
        where TParameterClass : DbParameter
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the Batabase Bulk Copy class. 
        /// </summary>
        /// <param name="taskName">
        /// Name of the data being bulk imported
        /// </param>
        /// <param name="sourceConnectionString">
        /// Connection String for the source database
        /// </param>
        /// <param name="sourceSql">
        /// SQL to get the source data
        /// </param>
        /// <param name="destinationConnectionString">
        /// Connection String for the target database
        /// </param>
        /// <param name="destinationDatabase">
        /// Name of the database the table sits in
        /// </param>
        /// <param name="destinationSchema">
        /// the schema the destination table sits in
        /// </param>
        /// <param name="destinationTable">
        /// the table the data is going to end up in
        /// </param>
        /// <param name="targetTableDeleteAction">
        /// the delete action to be taken on the target table
        /// </param>
        protected Database(
            string taskName, 
            string sourceConnectionString, 
            string sourceSql, 
            string destinationConnectionString,
            string destinationDatabase,
            string destinationSchema, 
            string destinationTable, 
            DestinationTableDeleteAction targetTableDeleteAction)
            : base(taskName, destinationConnectionString, destinationDatabase, destinationSchema, destinationTable, targetTableDeleteAction)
        {
            this.SourceConnectionString = sourceConnectionString;
            this.SourceSql = sourceSql;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Connection String for the source database
        /// </summary>
        private string SourceConnectionString { get; set; }

        /// <summary>
        /// SQL to get the source data
        /// </summary>
        private string SourceSql { get; set; }

        #endregion

        #region Methods

        /// <summary>
        /// Gets the db command for the source database
        /// </summary>
        /// <param name="sourceConnection">
        /// The source Connection.
        /// </param>
        /// <param name="sourceSql">
        /// The source Sql.
        /// </param>
        /// <returns>
        /// db command for the source database
        /// </returns>
        protected abstract DbCommand GetSourceDbCommand(DbConnection sourceConnection, string sourceSql);

        /// <summary>
        /// gets the db connection for the source db
        /// </summary>
        /// <param name="sourceConnectionString">
        /// The source Connection String.
        /// </param>
        /// <returns>
        /// db connection for the source db
        /// </returns>
        protected abstract DbConnection GetSourceDbConnection(string sourceConnectionString);

        /// <summary>
        /// Fetches the data and passes it on to be bulk inserted
        /// </summary>
        protected override void OnFetchAndProcessSourceData()
        {
            using (DbConnection sourceConnection = this.GetSourceDbConnection(this.SourceConnectionString))
            {
                sourceConnection.Open();

                DbCommand sourceCommand = this.GetSourceDbCommand(sourceConnection, this.SourceSql);

                var parameters = this.GetParameters();
                if (parameters != null)
                {
                    sourceCommand.Parameters.AddRange(parameters);
                }

                sourceCommand.CommandTimeout = 0;

                DbDataReader reader = sourceCommand.ExecuteReader();
                this.ActOnData(reader);
            }
        }

        /// <summary>
        /// Gets a list of parameters for the SQL command
        /// </summary>
        /// <returns>
        /// list of parameters for the SQL command
        /// </returns>
        protected abstract TParameterClass[] GetParameters();

        #endregion
    }
}